
#ifndef _LISTE_GENERIQUE
#define _LISTE_GENERIQUE

// Inclusion des modules utilises par le module Liste
// (A l'exclusion de ceux qui sont seulement utilises dans l'implantation :
//  ceux la sont inclus dans le fichier d'implantation)

#include "elemGen.H" //offrant le type Elem

struct Cellule
{
  Element info;
  Cellule *suivant;
};

struct Liste
{
  Cellule *ad;
  int nb_elem;
};

void initialise(Liste & l);
//Precondition : l non prealablement initialisee
//Postcondition : la liste l initialisee est vide

void initialise(Liste & l1, const Liste & l2, void(*p_init_elt)(Element &,Element));
//Precondition : l1 non prealablement initialisee, 
//               l2 prealablement initialisee et manipulee uniquement
//               a travers les operations du module 
//Postcondition : la liste l1 initialisee correspond à une copie de l2
// (mais les 2 listes sont totalement independantes l'une de l'autre)

void testament(Liste & l,void(*p_testament_elt)(Element &));
//Precondition : l prealablement initialisee et manipulee uniquement
//               a travers les operations du module
//Postcondition : l prete a etre detruite

void affectation(Liste & l1, const Liste & l2,void(*p_init_elt)(Element &,Element), void(*p_testament_elt)(Element &));
//Precondition : l1 et l2 prealablement initialisees et manipulees uniquement
//               a travers les operations du module
//Postcondition : la liste l1 correspond à une copie de l2
// (mais les 2 listes sont totalement independantes l'une de l'autre)

bool testListeVide(const Liste & l);
//Precondition : l prealablement initialisee et manipulee uniquement
//               a travers les operations du module
//Resultat : true si l est vide, false sinon

void premierElement(const Liste & l,void(*p_aff_elt)(Element));
//Precondition : testListeVide(l)==false
//Resultat : valeur de l'Elem contenu dans la 1ere Cellule

Cellule * premiereCellule(const Liste & l);
//Precondition : l initialisee et manipulee uniquement a travers les 
//                operations du module
//Resultat : adresse de la premiere cellule de l si testListeVide(l)==false
//           NULL sinon
//           Attention : la liste l pourra ensuite etre modifiee a travers 
//           la connaissance de l'adresse de sa premiere cellule

Cellule * celluleSuivante(const Cellule *c, const Liste & l);
//Precondition : c adresse valide d'une Cellule de la Liste l
//Resultat : adresse de la cellule suivante si elle existe
//           NULL sinon
//           Attention : la liste l pourra ensuite etre modifiee a travers 
//           la connaissance de l'adresse d'une de ses cellules

void elementCellule(const Cellule * c,void(*p_aff_elt)(Element));
//Precondition : c adresse valide d'une Cellule d'une Liste
//Resultat : valeur de l'Elem contenu dans la Cellule

void affichageListe(const Liste & l,void(*p_aff_elt)(Element));
//Precondition : l initialisee et manipulee uniquement a travers les 
//                operations du module
//Postcondition : Affichage exhaustif de tous les elements de l

void ajoutEnTete(const Element & e,Liste & l,void(*p_init_elt)(Element &,Element));
//Precondition : l et e initialises et manipules uniquement a travers les 
//                operations de leurs modules respectifs)
//Postcondition : L'Elem e est ajoute en tete de l 

void suppressionEnTete(Liste & l,void(*p_testament_int)(Element &));
//Precondition : testListeVide(l)==false
//Postcondition : la liste l perd son premier element

void videListe(Liste & l, void(*p_testament_elt)(Element &));
//Precondition : aucune 
//               (l initialisee et manipulee uniquement a travers les 
//                operations du module)
//Postcondition : testlisteVide(l)==true

void ajoutEnQueue(const Element & e,Liste & l,void(*p_init_elt)(Element &,Element));
//Precondition : l et e initialises et manipules uniquement a travers les 
//                operations de leurs modules respectifs
//Precondition : L'Elem e est ajoute en fin de la liste l

#endif
